package com.rt.tmpt.security;

import com.rt.tmpt.service.IMenuService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.security.access.ConfigAttribute;
import org.springframework.security.access.SecurityConfig;
import org.springframework.security.web.FilterInvocation;
import org.springframework.security.web.access.intercept.FilterInvocationSecurityMetadataSource;
import org.springframework.stereotype.Component;
import org.springframework.util.AntPathMatcher;

import javax.annotation.Resource;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Set;


/**
 * @Author: wuxiaoyong
 * @Date: 2020/01/28
 * @Description: 资源与权限对应关系
 * FilterInvocationSecurityMetadataSource（权限资源过滤器接口）继承了 SecurityMetadataSource（权限资源接口）
 * Spring Security是通过SecurityMetadataSource来加载访问时所需要的具体权限；Metadata是元数据的意思。
 * 自定义权限资源过滤器，实现动态的权限验证
 * 它的主要责任就是当访问一个url时，返回这个url所需要的访问权限
 **/
@Component
@Slf4j
public class MyFilterInvocationSecurityMetadataSource implements FilterInvocationSecurityMetadataSource {

    @Resource
    private IMenuService menuService;

    private AntPathMatcher antPathMatcher = new AntPathMatcher();


    /**
     * @Description: 返回本次访问需要的权限，可以有多个权限
     * @Date: 2019/3/27-17:11
     * @Param: [o]
     * @return: java.util.Collection<org.springframework.security.access.ConfigAttribute>
     **/
    @Override
    public Collection<ConfigAttribute> getAttributes(Object o) {
        String requestUrl = ((FilterInvocation) o).getRequestUrl();

        Collection<ConfigAttribute> configAttrList = new ArrayList<ConfigAttribute>();
        Set<String> authNameSet = menuService.getMenu2AuthListByUrl(requestUrl);
        System.out.println("authNameSet:" + authNameSet);
        if (authNameSet == null || authNameSet.size() == 0) {
            log.info("资源权限未分配:放行URL:{}", requestUrl);
            //throw new AccessDeniedException("资源权限未分配:"+requestUrl);
            return null;
        }

        log.info("当前访问路径是{},这个url所需要的访问权限是{}", requestUrl, authNameSet);
        for (String authName : authNameSet) {
            ConfigAttribute configAttr = new SecurityConfig(authName);
            configAttrList.add(configAttr);
        }

        return configAttrList;
    }

    /**
     * @Description: 此处方法如果做了实现，返回了定义的权限资源列表，
     * Spring Security会在启动时校验每个ConfigAttribute是否配置正确，
     * 如果不需要校验，这里实现方法，方法体直接返回null即可。
     * @Date: 2019/3/27-17:12
     * @Param: []
     * @return: java.util.Collection<org.springframework.security.access.ConfigAttribute>
     **/
    @Override
    public Collection<ConfigAttribute> getAllConfigAttributes() {
        return null;
    }

    /**
     * @Description: 方法返回类对象是否支持校验，
     * web项目一般使用FilterInvocation来判断，或者直接返回true
     * @Date: 2019/3/27-17:14
     * @Param: [aClass]
     * @return: boolean
     **/
    @Override
    public boolean supports(Class<?> aClass) {
        return FilterInvocation.class.isAssignableFrom(aClass);
    }



/*

	public Collection<ConfigAttribute> getAttributes(Object arg0)
			throws IllegalArgumentException {

		Collection<ConfigAttribute> configAttrList = new ArrayList<ConfigAttribute>();
		FilterInvocation fi = (FilterInvocation)arg0;
		String requestUrl = fi.getRequestUrl();


		int index = requestUrl.indexOf("?");
		int indexKeyRandom = requestUrl.indexOf("_keyRandom");
		int index_And = requestUrl.indexOf("&");

		//图表的URL中有
		//admin123/template/charts/single.jsp?_keyRandom=20161104142000001&_chartType=spline
		if(requestUrl.contains("_keyRandom") && requestUrl.contains("_chartType")){
			//url不做处理
		}
		else if(requestUrl.contains("_olapreportfilename=")){ //olap report filename ，取完整url地址
			//url不做处理
		}
		else if(index!=-1 && indexKeyRandom==-1){
			requestUrl = requestUrl.substring(0,index);
		}
		else if(index!=-1 && indexKeyRandom!=-1 && index_And!=-1){
			requestUrl = requestUrl.substring(0,index_And);
		}
		System.out.println("RequestUrl:"+requestUrl);

		//放行的URL
		///admin123/right_v2/securityv2Ajax_getCompanyDeptTree_access
		if(requestUrl.contains("_access")){
			ConfigAttribute configAttr = new SecurityConfig("_ACCESS");
			configAttrList.add(configAttr);
			return configAttrList;
		}

		Set<String> authNameSet = menuService.getMenu2AuthListByUrl(requestUrl);
		System.out.println("authNameSet:"+authNameSet);
		if(authNameSet==null || authNameSet.size()==0){
			System.out.println("资源权限未分配:"+requestUrl);
			throw new AccessDeniedException("资源权限未分配:"+requestUrl);
		}

		for(String authName:authNameSet){
			//System.out.println(authName+" = "+requestUrl);
			ConfigAttribute configAttr = new SecurityConfig(authName);
			configAttrList.add(configAttr);
		}

		return configAttrList;
	}
*/

}
